#!/usr/bin/env python
# -*- coding:utf-8 -*-
'''
@File    :   learn_Decorator.py
@Time    :   2025/01/09 22:44:52
@Author  :   xiangyu Chen
@Version :   1.0
@Contact :   yu112yu@sina.com
@License :   (C)Copyright 2017-2018, Liugroup-NLPR-CASIA
@python_requires    :   None
@Desc    :   装饰器
'''

# 无参装饰器


from datetime import datetime
from functools import partial, wraps
from time import localtime, strftime, time


def my_log(func):  # 定义一个能打印日志的 decorator
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper


@my_log
def now():
    print('2015-3-25')


now()


# 带参装饰器

def para_log(text):  # 定义一个带参数的 decorator
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s(): ' % (text, func.__name__), end='')
            return func(*args, **kw)
        return wrapper
    return decorator


@para_log('Decorator')
def nnow():
    print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))


nnow()
print('nnow().__name__ : ', nnow.__name__)

# 需要把原始函数的__name__等属性复制到 wrapper()函数中，否则，有些依赖函数签名的代码执行就会出错.Python 内置的 functools.wraps 就是干这个事的.


def wraps_log(text):  # 使用wraps复制原函数属性

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kw):
            print('%s %s(): ' % (text, func.__name__), end='')
            return func(*args, **kw)
        return wrapper
    return decorator


@wraps_log('Decorator had wraps method ')
def wraps_now():
    print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))


print('wraps_now().__name__ : ', wraps_now.__name__)


# ========================= 练习 exercises =================
def begin_end_decorators(text):  # 在函数调用的前后打印
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kw):
            print('%s %s(): begins...' % (text, func.__name__), end='')
            result = func(*args, **kw)
            print('    end call.')
            return result
        return wrapper
    return decorator


@begin_end_decorators('Function Call')
def print_message():
    print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))


print_message()


def parameterized_decorator(*a):  # 可传入参数，也可不传入参数。
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kw):
            print('Decorator %s with parameter %s is called.' %
                  (func.__name__, a))
            return func(*args, **kw)
        return wrapper
    return decorator


@parameterized_decorator('example')
def print_param():
    print('This is a parameterized decorator.')


print_param()


@parameterized_decorator()
def print_no_param():
    print('This is a decorator without parameter.')


print_no_param()


# =========================偏函数 =================
# functools.partial 的作用就是，把一个函数的某些参数给固定住（也就是设置默认值），返回一个新的函数，调用这个新函数会更简单。

int2 = partial(int, base=2)  # 二进制转十进制

print('int2(\'1011\')： ', int2('1011'))  # 1010转为10进制为10

# 创建偏函数时，实际上可以接收函数对象、*args 和**kw 这 3 个参数
max2 = partial(max, 10)  # 把 10 作为*args 的一部分自动加到左边

print('max2(5, 15)： ', max2(5, 9))
